package com.cctv.custom.hibernate.integrated.wrapper;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;

@SuppressWarnings("unchecked")
public abstract class HibernateDao implements CommonDao {

	@Override
	public void saveOrUpdate(Object obj) {
		getSession().saveOrUpdate(obj);
	}

	@Override
	public boolean delete(Object obj) {
		if (obj != null) {
			getSession().delete(obj);
			return true;
		}
		return false;
	}

	@Override
	public <T> boolean delete(Class<T> obj, Serializable id) {
		return delete(getSession().get(obj, id));
	}

	@Override
	public <T> T find(Class<T> obj, Serializable id) {
		T object = (T) getSession().get(obj, id);
		return object != null ? object : newInstance(obj);
	}

	private <T> T newInstance(Class<T> obj) {
		try {
			return obj.newInstance();
		} catch (Throwable e) {
			throw new RuntimeException();
		}
	}

	@Override
	public <T> List<T> list(Class<T> target,
			List<? extends Criterion> criterions) {
		return addCriterions(target, criterions).list();
	}

	private <T> Criteria addCriterions(Class<T> target,
			List<? extends Criterion> criterions) {
		Criteria criteria = getSession().createCriteria(target);
		for (Criterion criterion : criterions) {
			criteria.add(criterion);
		}
		return criteria;
	}

	@Override
	public <T> List<T> list(Class<T> target,
			List<? extends Criterion> criterions, Order[] orders) {
		return addOrders(addCriterions(target, criterions), orders).list();
	}

	private Criteria addOrders(Criteria criteria, Order[] orders) {
		for (Order order : orders) {
			criteria.addOrder(order);
		}
		return criteria;
	}

	@Override
	public <T> List<T> list(Class<T> target,
			List<? extends Criterion> criterions, int first, int pageSize,
			Order[] orders) {
		return addOrders(addCriterions(target, criterions), orders)
				.setFirstResult(first * pageSize).setMaxResults(pageSize)
				.list();
	}
}
